package db

import (
	"context"
	"fmt"
	log "github.com/sirupsen/logrus"
	"go.mongodb.org/mongo-driver/mongo"
	"go.mongodb.org/mongo-driver/mongo/options"
	"gorm.io/driver/mysql"
	"gorm.io/gorm"
	"sync"
	"time"
	"user-center/src/config"
	"user-center/src/model"
)

type Collection struct {
	ChatGroupsCollection *mongo.Collection
	MessagesCollection   *mongo.Collection
}

var (
	db         *gorm.DB
	dbOnce     sync.Once
	collection *Collection
)

func connectMySQL() {
	var err error
	dbInfo := config.GetGlobalConfig().DbConfig
	dsn := fmt.Sprintf("%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",
		dbInfo.User, dbInfo.Password, dbInfo.Url, dbInfo.DBName)
	db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		log.Fatalf("failed to connect database:%v", err)
		return
	}
	sqlDb, err := db.DB()
	if err != nil {
		log.Fatalf("get db.Db error %v", err)
	}
	sqlDb.SetMaxOpenConns(config.GetGlobalConfig().DbConfig.MaxOpenConn)
	sqlDb.SetMaxIdleConns(config.GetGlobalConfig().DbConfig.MaxIdleConn)
	sqlDb.SetConnMaxLifetime(time.Duration(config.GetGlobalConfig().DbConfig.MaxIdleTime))
	log.Info("Database connection is available")
}

func connectMongodb() {
	clientOptions := options.Client().ApplyURI("mongodb://" + config.GetGlobalConfig().MongodbConfig.Url)
	client, err := mongo.Connect(context.Background(), clientOptions)
	if err != nil {
		log.Fatal(err)
	}

	err = client.Ping(context.Background(), nil)
	if err != nil {
		log.Fatal(err)
	}

	log.Println("Connected to MongoDB!")
	// Initialize collections
	collection = &Collection{}
	collection.ChatGroupsCollection = client.Database(config.GetGlobalConfig().MongodbConfig.Database).Collection(model.GroupChat{}.TableName())
	collection.MessagesCollection = client.Database(config.GetGlobalConfig().MongodbConfig.Database).Collection(model.GroupMessage{}.TableName())

}

func connect() {
	connectMySQL()
	connectMongodb()
}

// GetMySQL 获取数据库连接
func GetMySQL() *gorm.DB {
	// 执行一次操作 懒加载
	dbOnce.Do(connect)
	return db
}

func GetMongo() *Collection {
	dbOnce.Do(connect)
	return collection
}
